package com.czk.netty.netty.codec2;

import com.czk.netty.netty.codec.StudentPOJO;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;

/**
 * netty服务端
 *
 * @Author:ChenZhangKun
 * @Date: 2021/1/13 22:28
 */
public class NettyServer {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = null;
        EventLoopGroup workerGroup = null;
        try {
            // boss处理连接请求
            // 默认的线程个数是cpu核心数*2 4核则产生八个子线程，workGroup是一样的
            bossGroup = new NioEventLoopGroup(1);
            // work处理业务请求 都是线程组
            // 两个都是无限循环
            workerGroup = new NioEventLoopGroup();
            // 创建服务端的启动对象，配置参数
            ServerBootstrap bootstrap = new ServerBootstrap();
            // 设置两个线程组
            bootstrap.group(bossGroup, workerGroup)
                    // 使用nioSocketChannel作为服务器通道实现
                    .channel(NioServerSocketChannel.class)
                    // 设置线程队列得到连接个数
                    .option(ChannelOption.SO_BACKLOG, 128)
                    // 保持活动连接的个数
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    // 创建一个通道测试端对象
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            // 加入编码器
                            socketChannel.pipeline().addLast("decoder",new ProtobufDecoder(MyDataInfo.MyMessage.getDefaultInstance()));
                            // 加入handler
                            socketChannel.pipeline().addLast(new NettyServerHandler());

                            // 拿到对应的channel
                            System.out.println(socketChannel.hashCode());

                        }
                    });
            System.out.println("服务器准备好了");
            // 绑定端口,并且同步处理
            ChannelFuture sync = bootstrap.bind(7000).sync();
            // 监听
            sync.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                    if (channelFuture.isSuccess()) {
                        System.out.println("监听端口成功");
                    } else {
                        System.out.println("监听端口失败");
                    }
                }
            });

            // 对关闭通道进行监听
            sync.channel().closeFuture().sync();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (bossGroup != null && workerGroup != null) {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }

        }

    }
}
